﻿using LightWadf.Processor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LightWadf.Route
{
    public class DefaultRoute
    {
        private RouteTrie index = new RouteTrie();
        private Dictionary<string, RouteTrie> tries = null;

        public DefaultRoute()
        {
            this.tries = new Dictionary<string, RouteTrie>();
        }

        public void MergeRoute(DefaultRoute route)
        {
            if (this.index.ProcessorName == null || this.index.MethodName == null)
            {
                this.index.ProcessorName = route.index.ProcessorName;
                this.index.MethodName = route.index.MethodName;
            }

            foreach (var item in route.tries)
            {
                if (this.tries.ContainsKey(item.Key))
                {
                    this.tries[item.Key].MergeTrie(item.Value);
                }
                else
                {
                    this.tries.Add(item.Key, item.Value);
                }
            }
        }

        public Tuple<RouteTrie, Dictionary<string, object>> Match(string url, string methodName = HttpMethod.Get)
        {
            if(url == null || !this.tries.ContainsKey(methodName))
                return null;
            else
            {
                if (url.Length == 0)
                {
                    // Index
                    return Tuple.Create<RouteTrie, Dictionary<string, object>>(this.index, null);
                }
                else
                {
                    string[] items = url.Split('/');
                    Queue<string> queue = new Queue<string>();
                    foreach (string item in items)
                    {
                        if (!string.IsNullOrEmpty(item))
                        {
                            queue.Enqueue(item);
                        }
                    }

                    if (queue.Count == 0)
                    {
                        return Tuple.Create<RouteTrie, Dictionary<string, object>>(this.index, null);
                    }

                    Dictionary<string, object> param = new Dictionary<string, object>();
                    RouteTrie trie = this.tries[methodName].Search(queue, param);
                    return Tuple.Create<RouteTrie, Dictionary<string, object>>(trie, param);
                }
            }
        }

        public void AddRouteRule(string routeRule, string processorName, string methodName, string method = HttpMethod.Get)
        {
            if (string.IsNullOrEmpty(routeRule) || string.IsNullOrEmpty(processorName) || string.IsNullOrEmpty(methodName)) return;
            string[] items = routeRule.Split('/');
            Queue<string> queue = new Queue<string>();
            foreach (string item in items)
            {
                if (!string.IsNullOrEmpty(item))
                {
                    queue.Enqueue(item);
                }
            }

            if (queue.Count == 0)
            {
                this.index.ProcessorName = processorName;
                this.index.MethodName = methodName;
                return;
            }

            if(this.tries.ContainsKey(method))
                this.tries[method].AddRoute(queue, processorName, methodName);
            else
            {
                RouteTrie trie = new RouteTrie();
                trie.AddRoute(queue, processorName, methodName);
                this.tries.Add(method, trie);
            }
        }
    }
}
